﻿using System;
using System.IO;
using System.Net;
using System.Windows;
using System.Windows.Browser;
using System.Windows.Threading;
using System.Collections.Generic;

using SBPweb.PROvibe.Shared.Contracts.Content;

using SBPweb.PROvibe.Client.Framework.Actors;
using SBPweb.PROvibe.Client.Framework.Actors.Parameters;
using SBPweb.PROvibe.Client.Framework.Contracts.Content;
using SBPweb.PROvibe.Client.Framework.Contracts.Parameters;
using SBPweb.PROvibe.Client.Framework.Content;
using SBPweb.PROvibe.Client.Framework.Modularity;
using SBPweb.PROvibe.Client.Framework.Utilities.Events;

namespace SBPweb.PROvibe.Client.Framework.Entry
{

    public partial class App : Application
    {

        #region Private fields

        //private const string ChannelUri = "{0}/Services/PollingDuplex.svc";
        //private const string ChannelNamespace = "SBPweb.PROvibe.Server/IServerChannel/SendMessage";
        //private ClientChannel channel;
        private IContentManager contentManager;
        private IThemeManager themeManager;
        private ClientDescriptor clientDescriptor;
        private IDictionary<string, string> entryParams;
        //private IEntryInitializationParametersDictionary entryParams;

        #endregion

        #region Constructor logic

        public App()
        {
            this.Startup += this.Application_Startup;
            this.Exit += this.Application_Exit;
            this.UnhandledException += this.Application_UnhandledException;

            InitializeComponent();
        }

        private void Application_Startup(object sender, StartupEventArgs e)
        {
            this.RootVisual = new RootVisual();
            InitializeEntryParameters(e.InitParams);
            InitializeContentManager();

            //string uri = this.Host.Source.AbsoluteUri;
            //uri = uri.Substring(0, uri.IndexOf("ClientBin") - 1);
            //channel = new ClientChannel(string.Format(ChannelUri, uri), ChannelNamespace, string.Empty, sessionId);
            //channel.AddHandler(typeof(KeepAliveContent), channel_KeepAliveReceived);
            //channel.AddHandler(typeof(InitializeLayoutContent), channel_InitializeLayoutReceived);
            //channel.Start();
        }

        private void Application_Exit(object sender, EventArgs e)
        {
        //    if (channel != null)
        //    {
        //        channel.RemoveHandler(typeof(KeepAliveContent), channel_KeepAliveReceived);
        //        channel.Stop();
        //    }
        }

        #endregion

        #region Property accessors

        //public ClientChannel Channel
        //{
        //    get
        //    {
        //        return channel;
        //    }
        //}

        public ClientDescriptor Client
        {
            get
            {
                if (ClientDescriptor.Empty.Equals(clientDescriptor))
                {
                    clientDescriptor = new ClientDescriptor(GetClientIp().ToString(), GetSessionId());
                }
                return clientDescriptor;
            }
        }

        //public IEntryInitializationParametersDictionary EntryParameters
        //{
        //    get
        //    {
        //        return entryParams;
        //    }
        //}

        internal RootVisual Root
        {
            get
            {
                return this.RootVisual as RootVisual;
            }
        }

        #endregion

        #region Methods

        #region Initialization

        private void InitializeEntryParameters(IDictionary<string, string> initParams)
        {
            entryParams = initParams;
            //if (entryParams != null)
            //{
            //    entryParams.Clear();
            //}
            //else
            //{
            //    entryParams = EntryInitializationParametersDictionary.Deserialize(initParams);
            //}
        }

        private void InitializeContentManager()
        {
            contentManager = new ContentManager();
            contentManager.Initialized += new EventHandler(contentManager_Initialized);
            contentManager.Loading += new EventHandler(contentManager_Loading);
            contentManager.Loaded += new EventHandler(contentManager_Loaded);
            contentManager.CurrentPageLoaded += new EventHandler<TypedObjectEventArgs<IPage>>(contentManager_CurrentPageLoaded);
            contentManager.Initialize(Client);
        }

        private void InitializeThemeManager()
        {
            contentManager.ThemeManagerLoaded += new EventHandler<TypedObjectEventArgs<IThemeManager>>(contentManager_ThemeManagerLoaded);
            contentManager.LoadCurrentThemeManager();
        }

        private string GetSessionId()
        {
            string ret = "N/A";
            if (entryParams.ContainsKey("SessionId"))
            {
                ret = entryParams["SessionId"].ToString();
            }
            return ret;
        }

        private IPAddress GetClientIp()
        {
            IPAddress ret = IPAddress.Parse("127.0.0.1");
            if (entryParams.ContainsKey("ClientIp"))
            {
                ret = IPAddress.Parse(entryParams["ClientIp"].ToString());
            }
            return ret;
        }

        #endregion

        #region Event handlers

        //private void channel_KeepAliveReceived(object sender, MessageContentEventArgs e)
        //{
        //    KeepAliveContent pmc = e.Content as KeepAliveContent;
        //    System.Diagnostics.Debug.WriteLine(string.Format("[{0}] ({1}) KeepAlive received: {2}\r\n", DateTime.Now, this.Host.Source, DateTime.FromFileTimeUtc(pmc.UtcTimeStamp)));
        //}

        //private void channel_InitializeLayoutReceived(object sender, MessageContentEventArgs e)
        //{
        //    InitializeLayoutContent ilc = e.Content as InitializeLayoutContent;
        //    System.Diagnostics.Debug.WriteLine(string.Format("[{0}] ({1}) InitializeLayout received.\r\n", DateTime.Now, this.Host.Source));
        //}

        private void contentManager_Initialized(object sender, EventArgs e)
        {
            InitializeThemeManager();
        }

        private void contentManager_Loading(object sender, EventArgs e)
        {
            Root.ShowLoaderSplash();
        }

        private void contentManager_Loaded(object sender, EventArgs e)
        {
            Root.HideLoaderSplash();
        }

        private void contentManager_CurrentPageLoaded(object sender, TypedObjectEventArgs<IPage> e)
        {
            Root.ShowPage(e.Object);
        }

        private void contentManager_ThemeManagerLoaded(object sender, TypedObjectEventArgs<IThemeManager> e)
        {
            themeManager = e.Object;
            themeManager.Initialized += new EventHandler(themeManager_Initialized);
            themeManager.Initialize();
        }

        private void themeManager_Initialized(object sender, EventArgs e)
        {
            contentManager.LoadCurrentPage();
        }

        #region Error handling

        private void Application_UnhandledException(object sender, ApplicationUnhandledExceptionEventArgs e)
        {
            // If the app is running outside of the debugger then report the exception using
            // the browser's exception mechanism. On IE this will display it a yellow alert 
            // icon in the status bar and Firefox will display a script error.
            if (!System.Diagnostics.Debugger.IsAttached)
            {

                // NOTE: This will allow the application to continue running after an exception has been thrown
                // but not handled. 
                // For production applications this error handling should be replaced with something that will 
                // report the error to the website and stop the application.
                e.Handled = true;
                Deployment.Current.Dispatcher.BeginInvoke(delegate { ReportErrorToDOM(e); });
            }
        }

        private void ReportErrorToDOM(ApplicationUnhandledExceptionEventArgs e)
        {
            try
            {
                string errorMsg = e.ExceptionObject.Message + e.ExceptionObject.StackTrace;
                errorMsg = errorMsg.Replace('"', '\'').Replace("\r\n", @"\n");

                System.Windows.Browser.HtmlPage.Window.Eval("throw new Error(\"Unhandled Error in Silverlight 2 Application " + errorMsg + "\");");
            }
            catch (Exception)
            {
            }
        }

        #endregion

        #endregion

        #endregion

    }

}